package cz.tomasdvorak.cars.utils;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Pomocne metody pro praci s mapami.
 */
public class Maps {
    /**
     * Vytvori novou {@link HashMap}u.
     */
    public static <K, V> HashMap<K, V> hashMap() {
        return new HashMap<K, V>();
    }

    /**
     * Vytvori novou {@link HashMap}u se zadanou pocatecni kapacitou.
     */
    public static <K, V> HashMap<K, V> hashMap(int initialCapacity) {
        return new HashMap<K, V>(initialCapacity);
    }

    /**
     * Vytvori novou {@link HashMap}u jako kopii zadane mapy.
     */
    public static <K, V> HashMap<K, V> hashMap(Map<K, V> map) {
        HashMap<K, V> newMap = new HashMap<K, V>();
        newMap.putAll(map);
        return newMap;
    }

    /**
     * Vytvori novou {@link LinkedHashMap}u.
     */
    public static <K, V> LinkedHashMap<K, V> linkedHashMap() {
        return new LinkedHashMap<K, V>();
    }

    /**
     * Vytvori novou {@link LinkedHashMap}u se zadanou pocatecni kapacitou.
     */
    public static <K, V> LinkedHashMap<K, V> linkedHashMap(int initialCapacity) {
        return new LinkedHashMap<K, V>(initialCapacity);
    }

    /**
     * Vytvori novou {@link LinkedHashMap}u jako kopii zadane mapy.
     */
    public static <K, V> LinkedHashMap<K, V> linkedHashMap(Map<K, V> map) {
        LinkedHashMap<K, V> newMap = new LinkedHashMap<K, V>();
        newMap.putAll(map);
        return newMap;
    }


    /**
     * Vytvori novou {@link ConcurrentHashMap}u.
     */
    public static <K, V> ConcurrentHashMap<K, V> concurrentHashMap() {
        return new ConcurrentHashMap<K,V>();
    }

    /**
     * Vytvori novou {@link ConcurrentHashMap}u se zadanou pocatecni kapacitou.
     */
    public static <K, V> ConcurrentHashMap<K, V> concurrentHashMap(int initialCapacity) {
        return new ConcurrentHashMap<K, V>(initialCapacity);
    }

    /**
     * Vytvori novou {@link ConcurrentHashMap}u jako kopii zadane mapy.
     */
    public static <K, V> ConcurrentHashMap<K, V> concurrentHashMap(Map<K, V> map) {
        ConcurrentHashMap<K, V> newMap = new ConcurrentHashMap<K, V>();
        newMap.putAll(map);
        return newMap;
    }


    /** <b>Neni</b> thread-safe! */
    public static class Builder<K, V> {
        LinkedHashMap<K, V> content = new LinkedHashMap<K, V>();

        public Builder<K, V> add(K key, V value) {
            content.put(key, value);
            return this;
        }

        public Builder<K, V> addAll(Map<K, V> map) {
            content.putAll(map);
            return this;
        }

        public HashMap<K, V> toHashMap() {
            return content;
        }

        public LinkedHashMap<K, V> toLinkedHashMap() {
            return content;
        }

        public ConcurrentHashMap<K, V> toConcurrentHashMap() {
            return new ConcurrentHashMap<K, V>(content);
        }
    }
}
